package ma.xin.shi.arxml.load.cherySomeip;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

import ma.xin.shi.arxml.comm.XmlParseComm;
import ma.xin.shi.arxml.load.cherySomeip.packages.Clusters.CherySomeipArxmlParserClusters;
import ma.xin.shi.arxml.load.cherySomeip.packages.DataTypes.CherySomeipArxmlParserDataTypes;
//import ma.xin.shi.arxml.load.cherySomeip.packages.DataTypes.CherySomeipArxmlParserDataTypes;
import ma.xin.shi.arxml.load.cherySomeip.packages.Executable.CherySomeipArxmlParserExecutable;
import ma.xin.shi.arxml.load.cherySomeip.packages.MachineManifest.CherySomeipArxmlParserMachineManifest;
import ma.xin.shi.arxml.load.cherySomeip.packages.Mappings.CherySomeipArxmlParserMappings;
import ma.xin.shi.arxml.load.cherySomeip.packages.ModeDeclarationGroups.CherySomeipArxmlParserModeDeclarationGroups;
import ma.xin.shi.arxml.load.cherySomeip.packages.Service.CherySomeipArxmlParserService;
import ma.xin.shi.arxml.load.cherySomeip.packages.ServiceInstance.CherySomeipArxmlParserServiceInstance;
import ma.xin.shi.arxml.load.cherySomeip.packages.ServiceInstantiation.CherySomeipArxmlParserServiceInstantiation;
import ma.xin.shi.arxml.load.cherySomeip.packages.SoftwareComponent.CherySomeipArxmlParserSoftwareComponent;
import ma.xin.shi.arxml.load.cherySomeip.packages.Topology.CherySomeipArxmlParserTopology;
import ma.xin.shi.arxml.load.cherySomeip.packages.TransformationProps.CherySomeipArxmlParserTransformationProps;

/**
 * ARXML 加载主流程控制类
 * 支持递归解析任意嵌套层级的 AR-PACKAGE
 */
public class CherySomeipArxmlLoadMain {

    private final List<ArxmlPackageParser> parsers;

    public CherySomeipArxmlLoadMain() {
        this.parsers = new ArrayList<>();
        initParsers();
    }

    private void initParsers() {
        parsers.add(new CherySomeipArxmlParserService());
        parsers.add(new CherySomeipArxmlParserSoftwareComponent());
        parsers.add(new CherySomeipArxmlParserExecutable());
        parsers.add(new CherySomeipArxmlParserTopology());
        parsers.add(new CherySomeipArxmlParserMachineManifest());
        parsers.add(new CherySomeipArxmlParserServiceInstantiation());
        parsers.add(new CherySomeipArxmlParserDataTypes());
        parsers.add(new CherySomeipArxmlParserMappings());
        parsers.add(new CherySomeipArxmlParserClusters());
        parsers.add(new CherySomeipArxmlParserModeDeclarationGroups());
        parsers.add(new CherySomeipArxmlParserTransformationProps());
        parsers.add(new CherySomeipArxmlParserServiceInstance());
    }

    /**
     * 加载并解析 ARXML 文件
     * @param filePath ARXML 文件路径
     */
    public void loadArxmlFile(String filePath) {
        try {
            File arxmlFile = new File(filePath);
            if (!arxmlFile.exists()) {
                XmlParseComm.logEx("文件不存在: " + filePath);
                return;
            }

            /*Document document = DocumentBuilderFactory.newInstance()
                    .newDocumentBuilder()
                    .parse(arxmlFile);*/
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            // 1. 开启命名空间支持（必须添加，否则无法读取 xsi:nil 等带命名空间的属性）
            factory.setNamespaceAware(true);
            // 2. 创建 DocumentBuilder（基于开启命名空间支持的工厂）DocumentBuilder 是 Java 中 专门处理 XML 的 API（JAXP） 的核心类，其设计用途就是将 XML 文本解析为内存中的 Document 对象（DOM 树结构）
            DocumentBuilder builder = factory.newDocumentBuilder();
            // 3. 解析文件为 Document 对象
            Document document = builder.parse(arxmlFile);
            document.getDocumentElement().normalize();

            Element root = document.getDocumentElement();
            Element packagesNode = XmlParseComm.getFirstChildElement(root, "AR-PACKAGES");
            if (packagesNode == null) {
                XmlParseComm.logEx("未找到 <AR-PACKAGES> 节点");
                return;
            }

            // 只获取直接子节点中的 AR-PACKAGE
            List<Element> topLevelPackages = getTopLevelPackages(packagesNode);
            XmlParseComm.logEx("发现 " + topLevelPackages.size() + " 个顶层模块");

            for (Element packageElement : topLevelPackages) {
                String packageName = XmlParseComm.getDirectChildTextContent(packageElement, "SHORT-NAME");
                XmlParseComm.logEx("=============> 正在解析顶层模块: " + packageName + " <============");
                parsePackageRecursive(packageElement, null);
            }
        } catch (Exception e) {
            XmlParseComm.logEx("解析 ARXML 出错: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 获取 AR-PACKAGES 节点下的所有直接 AR-PACKAGE 子元素
     */
    private List<Element> getTopLevelPackages(Element packagesNode) {
        List<Element> packages = new ArrayList<>();
        NodeList children = packagesNode.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            if (children.item(i) instanceof Element) {
                Element child = (Element) children.item(i);
                if ("AR-PACKAGE".equals(child.getTagName())) {
                    packages.add(child);
                }
            }
        }
        return packages;
    }

    /**
     * 解析 AR-PACKAGE 节点（仅处理顶层包，不递归子包）
     * @param packageElement 当前包节点
     * @param parentContext  上下文（预留参数）
     */
    private void parsePackageRecursive(Element packageElement, Object parentContext) {
        // 获取当前包的SHORT-NAME（直接子节点）
        String packageName = XmlParseComm.getDirectShortName(packageElement);
        if (packageName == null || packageName.trim().isEmpty()) {
            XmlParseComm.logEx("跳过无名称的 AR-PACKAGE");
            return;
        }

        XmlParseComm.logEx("开始解析模块: " + packageName);

        // 尝试匹配解析器（仅处理当前包，不递归子包）
        boolean parsed = false;
        for (ArxmlPackageParser parser : parsers) {
            if (parser.supports(packageName)) {// 判断当前解析器是否“支持”这个模块
                try {
                    XmlParseComm.logEx("使用解析器: " + parser.getClass().getSimpleName());
                    parser.parse(packageElement, parentContext);
                    parsed = true;
                    break;
                } catch (Exception e) {
                    XmlParseComm.logEx("解析失败 [" + packageName + "]: " + e.getMessage());
                    e.printStackTrace();
                }
            }
        }

        if (!parsed) {
            XmlParseComm.logEx("未找到支持的解析器: " + packageName);
        }

        XmlParseComm.logEx("完成解析模块: " + packageName + "\n");
    }

}
